﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Cube2
{   
    public class CModel
    {
        #region Field
        public Vector3 Positon { get; set; } //vị trí của vât
        public Vector3 Rotation { get; set; }//Quay vật
        public Vector3 Scale { get; set; }//Kéo dãn vật
        public Model Model { get; private set; }//Vật thể không gian

        private Matrix[] modelTranforms;//ma trận dùng để lưu cấu tạo vật thể
        private GraphicsDevice graphicDevice; //GraphicDevice
        private BoundingSphere boundingSphere;      
        #endregion

        /// <summary>
        /// Hàm khởi tạo CModel
        /// </summary>
        /// <param name="Model">Vật thể</param>
        /// <param name="Position">Vị trí</param>
        /// <param name="Rotation">Quay vật</param>
        /// <param name="Scale">Kéo dãn</param>
        /// <param name="graphicDevice">GraphicDevice</param>
        public CModel(Model Model, Vector3 Position, Vector3 Rotation, Vector3 Scale, GraphicsDevice graphicDevice)
        {
            this.Model = Model;
            this.Positon = Position;
            this.Rotation = Rotation;
            this.Scale = Scale;            
            this.graphicDevice = graphicDevice;
            modelTranforms= new Matrix[Model.Bones.Count];//khởi tạo ma trận bằng với số xương của Model
            Model.CopyAbsoluteBoneTransformsTo(modelTranforms);//Gán cho ma trận giá trị tạo nên Model
            builtBoudingSphere();           
        }
        /// <summary>
        /// Ý tưởng xét va chạm
        /// Load 1 Models nhỏ hơn vào đầu của con tàu và không Draw nó, để chế độ ẩn.
        /// Nếu va chạm thì con tàu sẽ đứng yên, không di chuyển nữa. Khi đó nó sẽ xoay 1 góc nào đó.
        /// Ok khi xoay thì model ảo sẽ ra ngoài vùng va chạm và con tàu tiếp tục di chuyển.
        /// </summary>
        private void builtBoudingSphere()
        {
            BoundingSphere sphere = new BoundingSphere(Vector3.Zero, 0);
            foreach (ModelMesh mesh in Model.Meshes)
            {              
                BoundingSphere tranformed = mesh.BoundingSphere.Transform(modelTranforms[mesh.ParentBone.Index]);
                sphere = BoundingSphere.CreateMerged(sphere, tranformed);//tao thanh 1 khoi

            }
            this.boundingSphere = sphere;
        }
       /// <summary>
       /// Kiểm tra va chạm với 1 model khác
       /// </summary>
       /// <param name="otherModel"></param>
       /// <returns></returns>
        public bool CheckColision(CModel otherModel)
        {

            return (this.BoudingSphere.Contains(otherModel.BoudingSphere) == ContainmentType.Intersects || this.BoudingSphere.Contains(otherModel.BoudingSphere)==ContainmentType.Contains);
        }
        /// <summary>
        /// Khối cầu bao quanh model
        /// </summary>
        public BoundingSphere BoudingSphere
        {
            get 
            {
                Matrix worldTranform = Matrix.CreateScale(Scale) * Matrix.CreateTranslation(Positon);
                BoundingSphere transformed = boundingSphere;
                transformed = transformed.Transform(worldTranform);
                return transformed;               
            }
        }
        /// <summary>
        /// Đây là hàm Draw 1 Model
        /// </summary>
        /// <param name="View">Ma trận View</param>
        /// <param name="Projection">Ma trận Projection</param>
        public void Draw(Matrix View,Matrix Projection)
        {
            //Đầu tiên khởi tạo 1 ma trận baseWorld
            //No là ma trận nhân của 3 ma trận: ma trận Kéo dãn, mt xoay, mt vị trí.
            Matrix baseWorld = Matrix.CreateScale(Scale) * Matrix.CreateFromYawPitchRoll(Rotation.Y,Rotation.X,Rotation.Z) * Matrix.CreateTranslation(Positon);
            //Duyệt từng Mesh trong Model đó
            foreach (ModelMesh mesh in Model.Meshes)
            {
                //Ma trận localWorld là 1 ma trận trong mảng ma trận modelTranforms với 1 chỉ số ParentBone tương ứng nhận với baseWorld
                Matrix localWorld= modelTranforms[mesh.ParentBone.Index]*baseWorld;
                //Duyệt từng phần trong Mesh
                foreach (ModelMeshPart partMesh in mesh.MeshParts)
                {
                    BasicEffect effect= (BasicEffect)partMesh.Effect;//Lấy ra effect
                    effect.EnableDefaultLighting();//Chiếu sáng mặc định
                    effect.World = localWorld;//Tạo world
                    effect.Projection = Projection;//Projection
                    effect.View = View;//Lookat
                }
                mesh.Draw();//Vẽ mesh
            }

        }

        
    }
}
